use criterion::{Criterion, criterion_group, criterion_main};
use std::os::raw::c_void;
use rb_tree::rb_tree::{RBTree, RBTreeCompareFunc, RBTreeKey, RBTreeValue, RbTreeNode, RBTreeNodeColor, RBTreeNodeSide};

fn compare_func(a: RBTreeValue, b: RBTreeValue) -> i32 {
    (a as usize).cmp(&(b as usize)) as i32
}

fn rb_tree_insert_benchmark(c: &mut Criterion) {
    let tree = RBTree::new(compare_func);
    c.bench_function("rb_tree_insert", |b| {
        b.iter(|| {
            for i in 0..1000 {
                tree.insert(i as *mut c_void, i as *mut c_void);
            }
        })
    });
}

fn rb_tree_lookup_benchmark(c: &mut Criterion) {
    let tree = RBTree::new(compare_func);
    for i in 0..1000 {
        tree.insert(i as *mut c_void, i as *mut c_void);
    }
    c.bench_function("rb_tree_lookup", |b| {
        b.iter(|| {
            for i in 0..1000 {
                tree.lookup(i as *mut c_void);
            }
        })
    });
}

fn rb_tree_remove_benchmark(c: &mut Criterion) {
    let tree = RBTree::new(compare_func);
    for i in 0..1000 {
        tree.insert(i as *mut c_void, i as *mut c_void);
    }
    c.bench_function("rb_tree_remove", |b| {
        b.iter(|| {
            for i in 0..1000 {
                tree.remove(i as *mut c_void);
            }
        })
    });
}

fn rb_tree_to_array_benchmark(c: &mut Criterion) {
    let tree = RBTree::new(compare_func);
    for i in 0..1000 {
        tree.insert(i as *mut c_void, i as *mut c_void);
    }
    c.bench_function("rb_tree_to_array", |b| {
        b.iter(|| {
            tree.to_array();
        })
    });
}

criterion_group!(
    benches,
    rb_tree_insert_benchmark,
    rb_tree_lookup_benchmark,
    rb_tree_remove_benchmark,
    rb_tree_to_array_benchmark
);
criterion_main!(benches);